import time

import requests
from flask import Flask, Response, request, render_template, jsonify
from volcenginesdkarkruntime import Ark
from tools.Utils import format_sse
from tools.redis import RedisClient
from tools.WeatherPlugin import get_weather_prompt
import os
import json
import oss2
import random
import json
from hashlib import md5
from tools.TTSPlugin import post_voice_synthesis, query_result

app = Flask(__name__)
app.config.from_mapping(
    VOLC_ACCESSKEY="api-key-20241228145506",
    VOLC_SECRETKEY="2bc40301-b4da-426c-9560-e0b302d50bf3",
    ENDPOINT_ID="ep-20241228145802-846zk",
    REDIS_URL="redis://localhost:6379/0",
    ENDPOINT='http://oss-cn-beijing.aliyuncs.com',
    RELIGION="oss-cn-beijing",
    ACCESS_KEY_ID="LTAI5t9ZJGqnXrYDFCVgejJM",
    ACCESS_KEY_SECRET="AsuPsigcdt3UxqWSHw1OlAsmu49KIw",
    BUCKET_NAME="moshangmm",
    UPLOAD_FOLDER="uploads",
    OCR_API_KEY="K82558702288957",
    AIDIAN_TIKU_API="http://new.api.51aidian.com/publics/newapi/oldapi",
    API_TOKEN="2fiviKLw0hYOmOrPxHSS"
)

# 初始化豆包AI客户端
client = Ark(api_key=app.config['VOLC_SECRETKEY'], region="cn-beijing")

# 初始化Redis客户端
redis_client = RedisClient(app.config['REDIS_URL'])

# 获取模型ID
model_id = app.config['ENDPOINT_ID']


def send_question_to_ai(question, chat_id):
    """发送问题到豆包AI并获取回答"""
    try:
        # 获取对话历史
        messages = redis_client.get_conversation_history_by_id(chat_id)

        # 添加当前问题
        messages.append({"role": "user", "content": question})

        # 获取天气提示词
        weather_prompt = get_weather_prompt(question, client, model_id)

        # 如果有天气相关提示词,添加到messages中
        if weather_prompt != "":
            messages.append({"role": "system", "content": weather_prompt})

        # 创建流式对话请求
        stream = client.chat.completions.create(
            model=model_id,
            messages=messages,
            stream=True
        )

        # 收集AI回复
        full_text = ""
        for chunk in stream:
            if chunk.choices:
                text = chunk.choices[0].delta.content
                full_text += text

        # 保存AI回复到对话历史
        messages.append({"role": "assistant", "content": full_text})

        # 保存对话历史到Redis
        redis_client.save_conversation_history(messages, chat_id)

        return full_text
    except Exception as e:
        print(f"处理请求时出错: {e}")
        return "抱歉，处理您的请求时出现了错误。"


def generateResponse(formatted_response):
    """生成流式响应"""
    for char in formatted_response:
        yield char.encode('utf-8')
        time.sleep(0.001)


def make_md5(s, encoding='utf-8'):
    return md5(s.encode(encoding)).hexdigest()


def get_access_token():
    """
    使用 API Key，Secret Key 获取access_token，替换下列示例中的应用API Key、应用Secret Key
    """

    url = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=2uymIVyHmMlHBkvsfatJz3v2&client_secret=o9DS0Xn526TC7PWZs4leMPW8NVwhrSwH"

    payload = json.dumps("")
    headers = {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    }

    response = requests.request("POST", url, headers=headers, data=payload)
    return response.json().get("access_token")


def translation_text(query, chat_id, from_lang, to_lang):
    # 获取对话历史
    messages = redis_client.get_conversation_history_by_id(chat_id)

    # 添加当前问题
    messages.append({"role": "user", "content": query})
    appid = '20241227002239831'
    appkey = '59VDgIK3vMA5k31tqa7k'
    endpoint = 'http://api.fanyi.baidu.com'
    path = '/api/trans/vip/translate'
    url = endpoint + path
    #query = 'Hello World! This is 1st paragraph.\nThis is 2nd paragraph.'
    # Generate salt and sign

    salt = random.randint(32768, 65536)
    sign = make_md5(appid + query + str(salt) + appkey)
    # Build request
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    payload = {'appid': appid, 'q': query, 'from': from_lang, 'to': to_lang, 'salt': salt, 'sign': sign}
    # Send request
    r = requests.post(url, params=payload, headers=headers)
    result = r.json()

    # Show response
    data = json.dumps(result, indent=4, ensure_ascii=False)
    # 将 JSON 字符串解析为字典
    result = json.loads(data)

    # 合并翻译内容
    merged_translation = "\n".join([item['dst'] for item in result['trans_result']])

    # 输出合并后的翻译内容
    print(merged_translation)
    # 保存AI回复到对话历史
    messages.append({"role": "assistant", "content": merged_translation})

    # 保存对话历史到Redis
    redis_client.save_conversation_history(messages, chat_id)

    return merged_translation


# 路由定义
@app.route('/')
def index():
    return render_template('chat.html')


@app.route('/ask', methods=['POST'])
def ask_question():
    """处理用户问题"""
    message = request.json['question']
    chat_id = request.json['chatId']
    response = send_question_to_ai(message, chat_id)
    formatted_response = format_sse(response)
    return Response(generateResponse(formatted_response), headers={'Content-Type': 'text/plain'})


# Redis相关路由
@app.route('/get_conversation_history', methods=['GET'])
def get_conversation_history():
    """获取对话历史"""
    return jsonify(redis_client.get_conversation_history())


@app.route('/save_chat_info', methods=['POST'])
def save_chat_info():
    """保存聊天信息"""
    data = request.get_json()
    redis_client.save_chat_info(data.get('chatId'), data.get('chatText'))
    return jsonify({"message": "聊天数据保存成功"})


@app.route('/get_chat_info', methods=['GET'])
def get_chat_info():
    """获取聊天信息"""
    return jsonify(redis_client.get_chat_info())


@app.route('/delete_chat_info', methods=['POST'])
def delete_chat_info():
    """删除聊天信息"""
    redis_client.delete_chat_info(request.get_json().get('chatId'))
    return jsonify({"message": "聊天数据删除成功"})


@app.route('/get_current_chat_id', methods=['GET'])
def get_current_chat_id():
    """获取当前对话ID"""
    return jsonify(redis_client.get_current_chat_id())


@app.route('/save_current_chat_id', methods=['POST'])
def save_current_chat_id():
    """保存当前对话ID"""
    chat_id = request.get_json().get('chatId')
    redis_client.save_current_chat_id(chat_id)
    if not redis_client.get_conversation_history_by_id(chat_id):
        messages = [{"role": "assistant", "content": "你好!我是AI助手,很高兴为您服务。请问有什么可以帮您?"}]
        redis_client.save_conversation_history(messages, chat_id)

    return jsonify({"message": "当前对话ID保存成功"})


@app.route('/generate_chat_id', methods=['GET'])
def generate_chat_id():
    """生成新的对话ID"""
    new_chat_id = redis_client.generate_chat_id()
    return jsonify({"chatId": new_chat_id})


# 初始化阿里云 OSS 客户端
auth = oss2.Auth(app.config['ACCESS_KEY_ID'], app.config['ACCESS_KEY_SECRET'])
bucket = oss2.Bucket(auth, app.config['ENDPOINT'], app.config['BUCKET_NAME'])


# 文件上传路由
def upload_image(file,from_lang,to_lang):

    if file.filename == '':
        return json.dumps({'success': False, 'message': 'No selected file'}), 400

    # 上传到 OSS
    filename = file.filename
    file_content = file.read()

    # 生成文件名，防止覆盖
    oss_file_name = f"uploads/{filename}"

    # # 上传文件到阿里云 OSS
    bucket.put_object(oss_file_name, file_content)
    #
    # # 返回上传成功的文件 URL
    file_url = f"https://{app.config['BUCKET_NAME']}.{app.config['ENDPOINT']}/{oss_file_name}"

    #填写Object完整路径，完整路径中不包含Bucket名称，例如testfolder/exampleobject.txt。
    # 下载Object到本地文件，并保存到指定的本地路径D:\\localpath\\examplefile.txt。如果指定的本地文件存在会覆盖，不存在则新建。
    bucket.get_object_to_file(oss_file_name, 'D:\\大三上\\SOA\\ai\\t.jpg')

    print("Download complete.")

    file_name = './t.jpg'
    url = 'https://aip.baidubce.com/file/2.0/mt/pictrans/v1?access_token=' + get_access_token()

    # Build request
    payload = {'from': from_lang, 'to': to_lang, 'v': '3', 'paste': '1'}
    image = {'image': (os.path.basename(file_name), open(file_name, 'rb'), "multipart/form-data")}
    # Send request
    response = requests.post(url, params=payload, files=image)
    result = response.json()

    # Show response
    data = json.dumps(result, indent=4, ensure_ascii=False)

    # 将 JSON 字符串解析为字典
    result = json.loads(data)
    result = result['data']['content']
    merged_src = ', '.join(item.get('src', '') for item in result if item.get('src'))
    merged_dst = ', '.join(item.get('dst', '') for item in result if item.get('dst'))
    merge = merged_src + '\n' + merged_dst
    for item in result:
        src = item.get('src')
        dst = item.get('dst')
        print(f"src: {src}, dst: {dst}")


    formatted_response = format_sse(merge)

    return Response(generateResponse(formatted_response), headers={'Content-Type': 'text/plain'})


@app.route('/translate', methods=['POST'])
def translate():
    message = request.form['question']
    chat_id = request.form['chatId']
    from_lang = request.form['from_lang']
    to_lang = request.form['to_lang']
    file = request.files.get('file')

    print(file)

    # Handling file
    file = request.files.get('file')
    if file and not message:
        # Process file here (e.g., save or handle it)
        response=upload_image(file, from_lang, to_lang)
        return response

    print(from_lang, to_lang)

    # Call translation function
    if message:
        response = translation_text(message, chat_id, from_lang, to_lang)
        formatted_response = format_sse(response)
        return Response(generateResponse(formatted_response), headers={'Content-Type': 'text/plain'})


@app.route('/synthesize_voice', methods=['POST'])
def synthesize_voice():
    try:
        data = request.get_json()
        text = data.get('text')
        voice_type = data.get('voice_type')

        if not text or not voice_type:
            return jsonify({'error': '缺少必要参数'}), 400

        # 提交语音合成任务
        task = post_voice_synthesis(text, voice_type)

        if not task or 'task_id' not in task:
            return jsonify({'error': '语音合成任务创建失败'}), 500

        task_id = task['task_id']

        # 轮询获取结果
        max_attempts = 10
        attempts = 0

        while attempts < max_attempts:
            time.sleep(2)  # 等待2秒
            result = query_result(task_id)

            if result and 'audio_url' in result:
                return jsonify({
                    'audio_url': result['audio_url']
                })

            attempts += 1

        return jsonify({'error': '语音合成超时'}), 500

    except Exception as e:
        print(f"Error in synthesize_voice: {str(e)}")
        return jsonify({'error': str(e)}), 500


@app.route('/upload_questionImage', methods=['POST'])
def upload_questionImage():
    print("请求到达 /upload_questionImage 路由")

    try:
        if 'file' not in request.files:
            return jsonify({"error": "未检测到上传的文件"}), 400

        file = request.files['file']
        if file.filename == '':
            return jsonify({"error": "未选择文件"}), 400

        # 打印文件信息
        print(f"文件名: {file.filename}, 内容类型: {file.content_type}")

        # # 检查文件类型
        # if not file.content_type.startswith('image/'):
        #     return jsonify({"error": "文件格式不支持"}), 400

        # 保存文件
        save_path = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
        os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)  # 确保文件夹存在
        file.save(save_path)
        # save_path = os.path.join('uploads', file.filename)
        # file.save(save_path)
        # return jsonify({"message": "文件上传成功", "filePath": save_path})

        # 调用 OCR 处理
        ocr_result = ocr_space_api(save_path, app.config['OCR_API_KEY'])
        print(f"OCR 结果: {ocr_result}")
        return jsonify({"ocrResult": ocr_result})

    except Exception as e:
        print(f"上传文件处理出错: {e}")
        return jsonify({"error": "文件处理失败"}), 500


@app.route('/search_question', methods=['POST'])
def search_question():
    """
    接收OCR提取的题目文本，并通过题库API进行搜题
    """
    try:
        data = request.get_json()
        question = data.get('question', '').strip()

        if not question:
            return jsonify({"error": "搜题内容不能为空"}), 400

        # 调用爱点题库API进行搜题
        answer = aidian_tiku_api(question)

        return jsonify({"answer": answer})

    except ValueError as ve:
        print(f"搜题失败: {ve}")
        return jsonify({"error": str(ve)}), 400
    except Exception as e:
        print(f"搜题处理出错: {e}")
        return jsonify({"error": "搜题失败，请稍后重试"}), 500


# OCRSpace API 调用函数
def aidian_tiku_api(question):
    """调用爱点题库 API 进行搜题"""
    try:
        # API请求
        response = requests.get(
            app.config['AIDIAN_TIKU_API'],
            params={'token': '2fiviKLw0hYOmOrPxHSS',
                    'question': question},
            timeout=10,  # 超时时间
            verify=False  # 跳过 SSL 校验
        )
        # 检查请求是否成功
        if response.status_code != 200:
            raise ValueError(f"请求失败，状态码：{response.status_code}")

        # 打印返回的原始数据
        print("API 返回数据:", response.text)
        # 解析JSON响应
        response.raise_for_status()
        result = response.json()
        # 检查返回格式
        if result.get('code') != 1:
            raise ValueError(f"接口返回错误: {result.get('msg')}")
        # 提取题目信息
        qlist = result.get('qlist', [])
        if not qlist:
            raise ValueError("未找到相关问题")
        # 返回问题及答案
        questions_with_answers = []
        for question_data in qlist:
            question_text = question_data.get('question', '')
            answer = question_data.get('answer', '')
            print('question_text', question_text)
            print('answer', answer)
            questions_with_answers.append({
                'question': question_text,
                'answer': answer})

        return questions_with_answers
    except requests.exceptions.RequestException as e:
        # 网络请求错误
        print(f"网络请求错误: {e}")
        raise ValueError(f"请求失败：{e}")
    except ValueError as e:
        # 数据格式错误
        print(f"数据格式错误: {e}")
        raise ValueError(f"数据格式错误：{e}")
    except Exception as e:
        print(f"搜题API错误: {e}")
        raise ValueError(f"搜题 API 错误: {e}")


def ocr_space_api(image_path, api_key):
    """调用 OCRSpace API 进行文字识别"""
    if not os.path.exists(image_path):
        raise ValueError("图片文件不存在")

    if os.path.getsize(image_path) > 1024 * 1024:  # 限制最大图片为1MB
        raise ValueError("图片文件过大，超过 1MB 限制")

    with open(image_path, 'rb') as image_file:
        response = requests.post(
            'https://api.ocr.space/parse/image',
            files={'image': image_file},
            data={'apikey': api_key, 'language': 'chs'}
        )

    # 打印完整响应数据
    print("OCR API 返回数据:", response.text)

    try:
        result = response.json()
    except ValueError:
        raise ValueError("OCR API 返回的内容不是有效的 JSON 格式")

    # 检查是否出错
    if result.get('IsErroredOnProcessing', False):
        error_message = result.get('ErrorMessage', ['未知错误'])[0]
        raise ValueError(f"OCR API 错误: {error_message}")

    # 检查结果格式
    if 'ParsedResults' not in result or not result['ParsedResults']:
        raise ValueError("OCR API 返回数据中缺少 ParsedResults")

    return result['ParsedResults'][0]['ParsedText']


if __name__ == "__main__":
    app.run(debug=True)
